//////////////////////////////////////////////////////////////////////////
//
// Vector Graph Core2D
//
// Module:
//        Transform2D.cs
//
// Description:
//        Implementation of coordinates transforming operation
//
// Author:
//        Created on 2008.04.17 by Destrayer
//
//////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Drawing2D;

namespace VectorGraph.Core2D
{
    class Transform2D
    {
        private WorldTransform2D worldTransform = new WorldTransform2D();
        private PageTransform2D pageTransform = new PageTransform2D();

        public WorldTransform2D WorldTransform
        {
            get { return this.worldTransform; }
            set { this.worldTransform = value; }
        }

        public PageTransform2D PageTransform
        {
            get { return this.pageTransform; }
            set { this.pageTransform = value; }
        }

        public void Translate(double dx, double dy)
        {
            this.worldTransform.Translate(dx, dy);
        }

        public void Rotate(double cosAngle, double sinAngle)
        {
            this.worldTransform.Rotate(cosAngle, sinAngle);
        }

        public void Scale(double scaleX, double scaleY)
        {
            this.worldTransform.Scale(scaleX, scaleY);
        }

        public void ResizePage(int pageHeight)
        {
            this.pageTransform.ResizePage(pageHeight);
        }

        public Matrix ToAffineMatrix()
        {
            Matrix2D m = new Matrix2D();
            m.Multiply(this.worldTransform);
            m.Multiply(this.pageTransform);
            return m.ToAffineMatrix();
        }

        public void WorldToDevice(ref Point2d pt)
        {
            this.worldTransform.WorldToPage(ref pt);
            this.pageTransform.PageToDevice(ref pt);
        }

        public void WorldToDevice(Point2d[] pts)
        {
            this.worldTransform.WorldToPage(pts);
            this.pageTransform.PageToDevice(pts);
        }

        public void DeviceToWorld(ref Point2d pt)
        {
            this.pageTransform.DeviceToPage(ref pt);
            this.worldTransform.PageToWorld(ref pt);
        }

        public void DeviceToWorld(Point2d[] pts)
        {
            this.pageTransform.DeviceToPage(pts);
            this.worldTransform.PageToWorld(pts);
        }
    }

    class WorldTransform2D : Matrix2D
    {
        public void WorldToPage(ref Point2d pt)
        {
            this.TransformPoint(ref pt);
        }

        public void WorldToPage(Point2d[] pts)
        {
            this.TransformPoints(pts);
        }

        public void PageToWorld(ref Point2d pt)
        {
            this.InverseTransformPoint(ref pt);
        }

        public void PageToWorld(Point2d[] pts)
        {
            this.InverseTransformPoints(pts);
        }
    }

    class PageTransform2D : Matrix2D
    {
        public void PageToDevice(ref Point2d pt)
        {
            this.TransformPoint(ref pt);
        }

        public void PageToDevice(Point2d[] pts)
        {
            this.TransformPoints(pts);
        }

        public void DeviceToPage(ref Point2d pt)
        {
            this.InverseTransformPoint(ref pt);
        }

        public void DeviceToPage(Point2d[] pts)
        {
            this.InverseTransformPoints(pts);
        }

        public void ResizePage(int pageHeight)
        {
            this.Reset();
            // reflect across x-axis
            this.m[3] = -1;
            // move origin to left-bottom
            this.Translate(0, -pageHeight);
        }
    }
}
